package cn.xuexiluxian.open.framework.security.filter;

import cn.hutool.core.util.StrUtil;
import cn.xuexiluxian.open.common.constant.CacheConstants;
import cn.xuexiluxian.open.common.constant.Constants;
import cn.xuexiluxian.open.common.enums.ResultStatusCodeEnum;
import cn.xuexiluxian.open.common.response.ResponseResult;
import cn.xuexiluxian.open.framework.security.RequestWrapper;
import cn.xuexiluxian.open.framework.security.exception.KaptchaExpiredException;
import cn.xuexiluxian.open.framework.security.exception.KaptchaValidateException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @Description
 * @Author 王俊南
 * @Date 2022/5/19 8:03 下午
 **/
@Component
@Slf4j
public class ImageCaptchaCodeValidateFilter extends OncePerRequestFilter implements InitializingBean {
    @Autowired
    private StringRedisTemplate redisTemplate;
    /**
     * 登录失败处理器
     */
    @Autowired
    private AuthenticationFailureHandler customAuthenticationFailureHandler;
    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        RequestWrapper requestWrapper = new RequestWrapper(request);
        boolean captchaOnOff = true;
        if(captchaOnOff) {
            response.setContentType("application/json;charset=utf-8");
            if (antPathMatcher.match(Constants.USERNAME_PASSWORD_LOGIN_URL, request.getRequestURI()) && "POST".equals(request.getMethod())) {
                try {
                    validate(requestWrapper);
                }catch (AuthenticationException e){
                    customAuthenticationFailureHandler.onAuthenticationFailure(request, response, e);
                    return;
                }
            }
        }

        filterChain.doFilter(requestWrapper, response);
    }

    /**
     * Description:从cookie中取出redis的kye，拿着key取出对应的value,验证图片验证码是否正确
     */
    private void validate(HttpServletRequest request) throws IOException {
        JSONObject jsonObject = new ObjectMapper().readValue(request.getInputStream(), JSONObject.class);

        if(!jsonObject.containsKey("key")){
            throw new KaptchaValidateException(ResultStatusCodeEnum.LOGIN_PARAM_REQUIRE_ERROR.getDesc());
        }
        String key = jsonObject.getString("key");
        String captcha = jsonObject.getString("captcha");

        String redisImageCode = redisTemplate.opsForValue().get(CacheConstants.IMAGE_CAPTCHA_PREFIX + key);
        /*获取图片验证码与redis验证*/
        /*redis的验证码不能为空*/
        if (StrUtil.isBlank(captcha)) {
            throw new KaptchaValidateException("验证码不能为空");
        }

        if (StrUtil.isBlank(redisImageCode)) {
            throw new KaptchaExpiredException("验证码已失效");
        }
        /*校验验证码*/
        if (!captcha.equalsIgnoreCase(redisImageCode)) {
            throw new KaptchaValidateException("验证码错误");
        }
        redisTemplate.delete(redisImageCode);
    }
}
